<html>
    <head>
        <title>当前用户</title>
    </head>
    <body>
        <script>
            // 当前用户  ICurrentUser

                    /*
                        ICurrentUser 是获取当前活动用户信息的主要服务。

                                eg: 将 ICurrentUser 注入服务：

                                        using System;
                                        using Volo.Abp.DependencyInjection;
                                        using Volo.Abp.Users;

                                        namespace AbpDemo
                                        {
                                            public class MyService : ITransientDependency
                                            {
                                                private readonly ICurrentUser _currentUser;

                                                public MyService(ICurrentUser currentUser)
                                                {
                                                    _currentUser = currentUser; // 注入 ICurrentUser 服务
                                                }
                                                
                                                public void Foo()
                                                {
                                                    Guid? userId = _currentUser.Id;
                                                }
                                            }
                                        }


                            常见的基类已经将此服务作为属性注入。
                            
                            例如，你可以直接使用应用程序服务中的CurrentUser属性：

                                        using System;
                                        using Volo.Abp.Application.Services;

                                        namespace AbpDemo
                                        {
                                            public class MyAppService : ApplicationService
                                            {
                                                public void Foo()
                                                {
                                                    Guid? userId = CurrentUser.Id;
                                                }
                                            }
                                        }
                    */

                    /*
                        二、属性  Properties

                                以下是 ICurrentUser 接口的基本属性：

                                    ①、IsAuthenticated（bool）：
                                    
                                            如果当前用户已登录（经过身份验证），则返回true。如果用户尚未登录，则Id和UserName返回null

                                    ②、Id（Guid？）：
                                    
                                            当前用户的ID。如果当前用户尚未登录，则返回null。

                                    ③、UserName（string）：
                                    
                                            当前用户的用户名。如果当前用户尚未登录，则返回null。

                                    ④、TenantId（Guid？）：
                                    
                                            当前用户的租户ID，这对多租户应用程序很有用。如果当前用户未分配给租户，则返回null。

                                    ⑤、Email（string）：
                                    
                                            当前用户的电子邮件地址。如果当前用户未登录或未设置电子邮件地址，则返回null。

                                    ⑥、EmailVerified (bool): 

                                            如果当前用户的电子邮件地址已被验证，则返回true。

                                    ⑦、PhoneNumber（string）：
                                            
                                            当前用户的电话号码。如果当前用户尚未登录或未设置电话号码，则返回null

                                    ⑧、PhoneNumberVerfied（bool）：

                                            如果当前用户的电话号码已被验证，则返回true。

                                    ⑨、Roles (string[]): 

                                            当前用户的角色。返回当前用户角色名称的字符串数组。
                    */


                    /*
                        三、方法  Methods

                                ICurrentUser 在 ICurrentPrincipalAccessor 上实现,并与声明一起使用。

                                因此,上述所有属性实际上都是从当前经过身份验证的用户的声明中检索的。


                                1、 用户声明 Claim:

                                        ICurrentUser 有一些方法可以直接处理声明：

                                            ①、FindClaim ：

                                                    获取给定名称的声明。如果未找到，则返回null.

                                            ②、FindClaims：

                                                    获取具有给定名称的所有声明（允许具有多个具有相同名称的声明值）。

                                            ③、GetAllClaims：

                                                    获取所有声明。

                                            ④、IsInRole：

                                                    一种快捷方法，用于检查当前用户是否处于指定角色。

                                2、扩展方法：

                                            ①、FindClaimValue：

                                                    获取具有给定名称的声明的值，如果未找到，则获取null。它有一个通用重载，也将值转换为特定类型。

                                            ②、GetId：

                                                    返回当前用户的Id。
                                                    
                                                    如果当前用户尚未登录，它会引发异常（而不是返回null）。
                                                    
                                                    仅当你确定用户已经在你的代码上下文中进行了身份验证时才使用此选项。

                    */

                    /*
                        四、认证和授权  Authentication & Authorization


                                    ICurrentUser 独立于用户的身份验证或授权方式工作。


                                    它不任何与当前主体一起使用的身份验证系统无缝协作。


                    */

                    /*
                        五、当前主体接口 ICurrentPrincipalAccessor

                                ICurrentPrincipalAccessor 是当需要使用当前用户的当前主体(Principal)时使用的接口。

                                用来获取当前用户的当前主体。

                                对于Web应用程序而言，它获取当前 HttpContext 的 User属性。

                                对于非Web应用程序，它返回 Thread.CurrentPrincipal。


                                你通常不需要使用这种底层的 ICurrentPrincipalAccessor 服务，只需要使用上面的 ICurrentUser 服务就好。


                                1、基本用法：

                                        你可以将ICurrentPrincipalAccessor注入并使用Principal属性到当前主体：

                                            eg:

                                                public class MyService : ITransientDependency
                                                {
                                                    private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;

                                                    public MyService(ICurrentPrincipalAccessor currentPrincipalAccessor)
                                                    {
                                                        _currentPrincipalAccessor = currentPrincipalAccessor; // 注入 ICurrentPrincipalAccessor 服务
                                                    }
                                                    
                                                    public void Foo()
                                                    {
                                                        // 获取当前主题的所有声明
                                                        var allClaims = _currentPrincipalAccessor.Principal.Claims.ToList();
                                                    }
                                                }

                                2、更改当前主题：

                                        当前主体不是你想要设置或更改的对象，除非在某些高级方案中。

                                        如果需要，请使用ICurrentPrincipalAccessor的Change方法。它接受一个ClaimsPrincipal对象，并将其设为范围的“当前”。


                                        eg:
                                            public class MyAppService : ApplicationService
                                            {
                                                private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;

                                                public MyAppService(ICurrentPrincipalAccessor currentPrincipalAccessor)
                                                {
                                                    _currentPrincipalAccessor = currentPrincipalAccessor;
                                                }

                                                public void Foo()
                                                {
                                                    // 创建一个新的ClaimsPrincipal对象，并将其设置为当前主体。
                                                    var newPrincipal = new ClaimsPrincipal(
                                                        new ClaimsIdentity(
                                                            new Claim[]
                                                            {
                                                                new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()),
                                                                new Claim(AbpClaimTypes.UserName, "john"),
                                                                new Claim("MyCustomCliam", "42")
                                                            }
                                                        )
                                                    );

                                                    // 始终在using语句中使用Change方法，因此在using范围结束后，它将恢复为原始值。
                                                    using (_currentPrincipalAccessor.Change(newPrincipal))
                                                    {
                                                        var userName = CurrentUser.UserName; //returns "john"
                                                        //...
                                                    }
                                                }
                                            }

                                        始终在using语句中使用Change方法，因此在using范围结束后，它将恢复为原始值。

                                        这可能是一种模拟应用程序代码作用域的用户登录的方法，但是请谨慎使用它。
                    */
                    
                    /*
                        六、声明类型 AbpClaimTypes 

                               AbpClaimTypes是一个静态类，它定义标准声明的名称并由ABP使用：
                               
                                    UserName、UserId、Role和Email属性的默认值是从System.Security.Claims类设置的。 ClaimTypes类，但你可以更改它们。

                                    其他属性，如EmailVerified、PhoneNumber、TenantId…由ABP通过尽可能遵循标准名称来定义。

                                    其他属性，如EmailVerified、PhoneNumber、TenantId…由ABP通过尽可能遵循标准名称来定义。
                    */

                   
        </script>
    </body>
</html>